import { Route } from "f2e-serve";
import { IncomingMessage, ServerResponse } from "http";
import { ConfigObject } from 'svg-captcha'

export interface Props {
    id?: number | string
    name: string
    isSys?: boolean
}
export enum Level {
    NONE, READ, ADD, UPDATE, CONFIG
}
export interface Authority extends Props {
}

export interface Role extends Props {
    authorities: {
        [authorityId: number]: Level
    }
    isAdmin?: boolean
}

export interface User extends Props {
    nickname?: string
    password: string
    token?: string
    roleId?: number
    role?: Role
    /**
     * IP锁定
     */
    lock_ips?: string[]
    /**
     * 到期日期
     */
    expires?: number
    /**
     * 当前登录IP
     */
    login_ip?: string
}

type IDType = string
export interface Store {
    createToken: (account: { name: string, password: string }) => string

    authorities: () => Authority[] | Promise<Authority[]>
    roles: () => Role[] | Promise<Role[]>
    users: () => User[] | Promise<User[]>

    addRole: (roleName: IDType) => any | Promise<any>
    delRole: (roleId: IDType) => void | Promise<void>
    addUser: (userName: string, password: string, nickname?: string) => number | Promise<number>
    delUser: (userId: IDType) => void | Promise<void>

    changeUserPassword?: (userId: IDType, password?: string) => void | Promise<void>
    updateRoleAuthority: (roleId: IDType, authorityId: IDType, level: Level) => void | Promise<void>
    updateUserRole: (userId: IDType, roleId: IDType) => void | Promise<void>
    updateUserLockIPs?: (userId: IDType, ips: string[]) => void | Promise<void>
    updateUserExpires?: (userId: IDType, expires: number) => void | Promise<void>

    getLoginUser: (key: string) => User | undefined
    lookLoginUser: (key: string) => Promise<User | undefined>

    /**
     * 是否支持修改密码
     */
    usePasswordChange?: boolean
    /**
     * 不允许新增用户
     */
    noAddUser?: boolean
    /**
     * jira 的api接口根路径
     */
    apiRoot?: string
    /**
     * Store内支持配置多组路由，用于已登录用户的接口
     */
    routes?: Parameters<Route['on']>[]
}
export interface RequestWith<T = any> extends IncomingMessage {
    loginUser: User
    post?: T
    data: T
}

export interface LoginStateItem {
    IP: string,
    crsf_token: string,
    error_count: number,
    clear_timer?: NodeJS.Timer,
    captcha_text?: string,
}

export interface SessionItem {
    session: string,
    ip: string,
    expire: number,
}
export interface ErrorMessage {
    /** 旧密码输入错误 */
    wrong_old_pass?: string
    /** 新密码格式错误 */
    wrong_new_pass?: string
    /** 新密码两次输入不一致 */
    no_match_pass?: string

    /** 不合法请求 */
    no_token?: string
    /** 验证码错误 */
    wrong_captcha?: string
    /** IP锁定请稍后重试 */
    account_lock?: string,
    /** 用户名或密码错误 */
    wrong_pass?: string,
    /** 登录账号已过期 */
    expires?: string,
    /** 登录IP不被允许 */
    lock_ips?: string,
    /** 无用户角色 */
    no_role?: string,

    /** 账户登录IP变更 */
    ip_change?: string,
}
export interface Config {
    /** 开启dev模式，方便开发环境调试,外部使用请勿开启 */
    dev?: boolean
    /** f2e-server 中间件保留参数 */
    setBefore: 0

    /** session 在浏览器超时时间 */
    maxAge?: number
    store?: Store
    /** 请求拦截匹配, 默认为 .* */
    test?: RegExp

    layout_page?: string
    login_page?: string
    admin_page?: string
    style_content?: string
    js_content?: string

    get_layout_page?: () => string
    get_login_page?: () => string
    get_admin_page?: () => string

    /** 默认支持url跳转, 可以关闭、http安全检查 */
    with_login_search?: false | {(req: IncomingMessage): Promise<string>}

    login_url?: string
    /** 替代login请求逻辑, 必须自行处理response输出 */
    login_execute?: (req: RequestWith, resp: ServerResponse) => Promise<void>
    logout_url?: string
    admin_url?: string

    /**
     * 添加用户回调
     */
    onAddUser?: (req: RequestWith<{ name: string, nickname: string}>) => void
    /**
     * 更新用户角色回调
     */
    onUpdateRole?: (req: RequestWith<{userId: string, roleId: string}>) => void
    /**
     * 删除用户回调
     */
    onDeleteUser?: (req: RequestWith<{userId: string}>) => void
    /**
     * session change 回调
     */
    onSessionChange?: (token_map_session: {[k:string]: string}) => void
    /**
     * 登录回调
     */
    onLogin?: (req: RequestWith<{ name: string, passowrd: string }>) => Promise<void>
    /**
     * 是否接口返回(JSON格式)
     */
    isJsonOut?: (req: RequestWith<any>) => boolean
    /**
     * 通过JSON格式接口获取crsf_token时,修改crsf_token
     * 抛出异常时, 将异常信息以字符串形式返回
     */
    onGetCrsfToken?: (req: RequestWith, crsf_token?: string) => Promise<string>

    /**
     * 登录出错5次后锁定 
     */
    login_error_times?: number
    /**
     * 锁定时间 默认1分钟 
     */
    login_error_remain?: number
    /**
     * 使用图片验证码
     */
    login_captcha?: ConfigObject
    /**
     * 错误信息提示
     */
    error_message?: ErrorMessage
    
    /**
     * 展示用户失效日期配置
     */
    user_expires?: boolean
    /**
     * 展示用户IP锁定配置
     */
    user_ip_lock?: boolean

    /**
     * 支持头像配置
     */
    use_avatar?: boolean
    /**
     * 头像大小限制 默认为100K： 100 * 1024
     */
    avatar_size?: number

    /**
     * 权限级别设置 可以设置level 1-N 的对应展示
     * @default null 默认展示选中与否 level 为 1
     * @example ['读取', '新增', '修改', '配置']
     */
    auth_level?: string[]
}